#pragma once
#include<sys/epoll.h>
#include<functional>
#include"Epoll.h"
#include"InetAddress.h"
#include"Socket.h"
#include"Connection.h"


class Epoll;
class Connection;
class EventLoop;

class Channel
{
private:
    // Channel拥有的fd，一个 Channel 对应一个 fd
    int fd_ = -1;
    // 由于EventLoop和Epoll是一一对应的，故这里存储EventLoop也是一样的
    // Channel对应的红黑树，Channel 与 Epoll 是多对一的关系 [正好与上面的fd对应了，一个epoll对象可以添加很多个fd，而Channel与fd又是一一对应的]
    EventLoop *loop_ = nullptr;
    // 判断Channel 是否已经添加到了红黑树上，如果未添加，在调用 epoll_ctl 的时候使用 EPOLL_CTL_ADD ，否则使用 EPOLL_CTL_MOD
    bool inepoll_ = false;
    // fd_ 需要监视的事件，例：读事件或者写事件； listenfd和clientfd需要监视 EPOLLIN，clientfd可能还需要监视EPOLLOUT，某些fd可能需要设置为边缘触发
    uint32_t events_ = 0;
    // 本轮循环fd在epoll中触发的事件
    uint32_t revents_ = 0;
    // 读事件的回调函数,如果是Acceptor中的channel，将回调Acceptor::newconnection。如果的clientchannle，会回调Connection::onmessage
    std::function<void()> readcallback_;
    // 关闭fd的回调函数，将回调Connection::closecallback()
    std::function<void()> closecallback_;
    // 关闭fd的回调函数，将回调Connection::errorcallback()
    std::function<void()> errorcallback_;
    // 写事件的回调函数，会回调Connection::writecallback()
    std::function<void()> writecallback_;
public:
    // 构造函数
    Channel(EventLoop *loop, int fd);  // Channel 是 Acceptor 和 Connection 的下层类
    // 析构函数
    ~Channel();
    // 返回fd_成员
    int fd();
    // 采用边缘触发
    void setet();
    // 设置监听读事件
    void enablereading();
    // 设置取消监听读事件
    void disablereading();
    // 设置监听写事件
    void enablewriting();
    // 设置取消监听写事件
    void disablewriting();
    // 取消全部的事件
    void disableall();
    // 从事件循环中删除这个Channel
    void remove();
    // 将inepoll_的值设置为true
    void setinepoll();
    // 修改revents_的值
    void setrevents(uint32_t ev);
    // 获取inepoll_的值
    bool inpoll();
    // 获取events_成员
    uint32_t events();
    // 获取revents_成员
    uint32_t revents();
    // 事件处理函数，epoll_wait函数返回当前fd的事件时，执行它
    void handleevent();
    // 设置读事件的回调函数
    void setreadcallback(std::function<void()> fn);
    // 设置断开连接时的回调函数
    void setclosecallback(std::function<void()> fn);
    // 设置fd发生错误时的回调函数
    void seterrorcallback(std::function<void()> fn);
    // 设置写事件的回调函数
    void setwritecallback(std::function<void()> fn);
};

